<?php

Raise::load('core.ui.RaiseUIControl');
Raise::load('core.reflection.RaiseVariable');
Raise::load('core.geometry.RaisePoint');
Raise::load('core.text.html.RaiseHtmlTag');

/**
 * RaiseProgressBar UIControl class
 * Creates a RaiseUIControl that is displayed as a progress bar
 *
 * @author Sam-Mauris Yong / hellclanner at live dot com
 * @license http://www.opensource.org/licenses/bsd-license New BSD License
 * @package phpraise.control
 * @since 1.2
 */
class RaiseProgressBar extends RaiseUIControl {

    /**
     * Set whether to use HTML5 &lt;progress&gt; tag instead of classic &lt;div&gt; tags.
     * @var boolean
     */
    private $useHTML5 = false;

    /**
     * The value of the progress bar, from 0 - $max
     * @var integer|double
     */
    private $value = 0;

    /**
     * The maximum value of the progress bar
     * @var integer|double
     */
    private $max = 0;

    /**
     * The size dimension of the RaiseProgressBar
     * @var RaisePoint
     */
    private $size;

    /**
     * Create a new RaiseProgressBar
     * @param integer|double $value (Optional) Current value of the progress bar
     * @param integer|double $max (Optional) Maximum value of the progress bar
     */
    public function __construct($v = 0, $m = 100) {
        $this->max($m);
        $this->value($v);
    }

    /**
     * Get or set whether to use HTML5 &lt;progress&gt; or legacy &lt;div&gt; progress bar
     *  - TRUE indicates to use &lt;progress&gt; progress bar
     *  - FALSE indicates to use legacy &lt;div&gt; progress bar
     * @param boolean $useHTML5 (Optional) The value to set
     * @return boolean
     */
    public function useHTML5($h = false){
        if(func_num_args() == 1){
            if(!RaiseVariable::isType($h, RaiseVariable::TYPEBOOLEAN)){
                throw new RaiseInvalidArgumentException('$useHTML5 is not a boolean. The useHTML5 flag requires a TRUE or FALSE boolean');
            }
            $this->useHTML5 = $h;
        }
        return $this->useHTML5;
    }

    /**
     * Get or set the size of the RaiseProgressBar
     * If no arguments are passed in, the method returns a Point which indicate the size of this UI Control
     * @param RaisePoint|integer|double $v (Optional) The size of the element, or the width
     * @param integer|double $a (Optional) The height of the element
     * @return RaisePoint
     */
    public function size($v = false, $a = false){
        $n = func_num_args();
        if($n == 2){
            if(!RaiseVariable::isNumeric($v)){
                throw new RaiseInvalidArgumentException('$width is not a numeric variable (i.e. integer or double). Width requires a number.');
            }
            if(!RaiseVariable::isNumeric($a)){
                throw new RaiseInvalidArgumentException('$height is not a numeric variable (i.e. integer or double). Height requires a number.');
            }
            if($v <= 0 || $a <= 0){
                throw new RaiseInvalidArgumentException('$width and $height must not be less than or equal to zero');
            }
            $this->size = new RaisePoint($v, $a);
        }elseif($n == 1){
            if(!($v instanceof RaisePoint)){
                throw new RaiseInvalidArgumentException('$size is not a RaisePoint object. It must be a RaisePoint object indicating the width and height of the RaiseProgresssBar.');
            }
            $this->size = $v;
        }
        return $this->size;
    }

    /**
     * Get or set the value of RaiseProgressBar
     * @param integer|double $v (Optional) The value to set
     * @return integer|double
     */
    public function value($v = false){
        if($v !== false){
            if(!RaiseVariable::isNumeric($v)){
                throw new RaiseInvalidArgumentException('$value is not a numeric variable (i.e. integer or double). Value requires a number.');
            }
            if($v > $this->max){
                throw new RaiseInvalidArgumentException('$value must be lower than $max, the maximum value of the progress bar.');
            }
            $this->value = $v;
        }
        return $this->value;
    }

    /**
     * Get or set the maximum value of RaiseProgressBar
     * @param integer|double $m (Optional) The value to set
     * @return integer|double
     */
    public function max($m = false){
        if($m !== false){
            if(!RaiseVariable::isNumeric($m)){
                throw new RaiseInvalidArgumentException('$max is not a numeric variable (i.e. integer or double). Maximum value requires a number.');
            }
            if($this->value > $m){
                throw new RaiseInvalidArgumentException('$value must be lower than $max, the maximum value of the progress bar.');
            }
            $this->max = $m;
        }
        return $this->max;
    }

    /**
     * Return the Javascript code that you can run on client side to update the progress of this RaiseProgressBar
     * @param integer|double $i
     * @return string
     */
    public function clientUpdateValue($i){
        if(!RaiseVariable::isNumeric($i)){
            throw new RaiseInvalidArgumentException('$value is not a numeric variable (i.e. integer or double). Value requires a number. ');
        }
        if($this->clientId){
            if($this->useHTML5){
                return 'if(!phpRaise){alert(\'phpRaise Error CE01\');};phpRaise.select(\''.$this->clientId().'\').value = '.$i.';';
            }else{
                return 'if(!phpRaise){alert(\'phpRaise Error CE01\');};phpRaise.select(\''.$this->clientId().'value\').style.width = \''.($i / $this->max * 100).'\';';
            }
        }else{
            if($this->useHTML5){
                return 'if(!phpRaise){alert(\'phpRaise Error CE01\');};phpRaise.select(\''.$this->uniqueId().'\').value = '.$i.';';
            }else{
                return 'if(!phpRaise){alert(\'phpRaise Error CE01\');};phpRaise.select(\''.$this->uniqueId().'value\').style.width = \''.($i / $this->max * 100).'\';';
            }
        }
    }

    /**
     * Return the default styling for non-HTML5/div-based progress bars
     * @return string
     * @static
     */
    public static function cssStyle(){
        return '.raiseProgressBar{background:#FFF; padding: 1px; border:1px solid #CCC;} .raiseProgressBar>div{color:#FF;background:#0A0;height:100%;}';
    }

    /**
     * Return the HTML output for this RaiseProgressBar
     * @return string The final output of this RaiseProgressBar
     */
    public function output() {
        if($this->useHTML5){
            $tag = new RaiseHtmlTag('progress', ' ');
            $tag->attributes()->add('value',$this->value());
            $tag->attributes()->add('max', $this->max());
            $tag->attributes()->add('style', 'width: '.$this->size()->x().'px;height: '.$this->size()->y().'px;');
        }else{
            $tag = new RaiseHtmlTag('div');
            $tag->attributes()->add('class', 'raiseProgressBar');
            $tag->attributes()->add('style', 'width: '.$this->size()->x().'px;height: '.$this->size()->y().'px;');

            $value = new RaiseHtmlTag('div', ' ');
            if($this->clientId()){
                $value->attributes()->add('id', $this->clientId().'value');
            }else{
                $value->attributes()->add('id', $this->uniqueId().'value');
            }
            $value->attributes()->add('style', 'width: '.($this->value() / $this->max() * 100).'%;');
            $tag->children()->add($value);
        }
        if($this->clientId()){
            $tag->attributes()->add('id', $this->clientId());
        }else{
            $tag->attributes()->add('id', $this->uniqueId());
        }
        return $tag->html();
    }

}